常见问题

在这里,我们试着回答一些经常出现在邮件列表中的问题。

项目名称是什么(很多人弄错了)?

scikit-learn,但不是scikit或SciKit也不是sci-kit learn。 同样不是先前使用的scikits.learn或scikits-learn。

项目名称如何发音?

sy-kit learn。 sci代表科学!

为什么选择 scikit ?

有多个scikits,它们是围绕SciPy构建的科学工具箱。 您可以在这里https://scikits.appspot.com/scikits找到一个列表。 除了scikit-learn,另一个流行的是scikit-image

我如何为 scikit-learn 做贡献?

贡献。添加一个新算法(通常是一项重大而漫长的工作)之前,建议先从已知问题开始。请不要直接联系scikit- learn的作者。

获取 scikit-learn 用法帮助的最佳方法是什么?

对于一般的机器学习问题 , 请在Cross Validated 网站下找到[machine-learning]的tag。

对于 scikit-learn 用法问题,请在Stack Overflow网站下找到[scikit-learn][python]的tag。您也可以使用邮件列表

请确保包含一个最小的复制代码片段(最好短于10行),在toy数据集(例如从'sklearn.datasets'或使用带有固定随机种子的'numpy.random'函数随机生成)上显示您的问题。请删除任何跟问题无关的代码行。

如果您只是简单地把代码片段复制粘贴到安装了scikit-learn的Python shell命令行中的话,可能会重新出现该问题。不要忘记复制导入代码的语句(import)。

有关编写良好的可重复利用代码段的更多指导,请参见:https://stackoverflow.com/help/mcve

如果您的问题引发了一个您不理解的异常(即使在对该问题进行了搜索之后),也请确保包括您在运行脚本时的完整异常信息。

对于bug的报告或功能请求,请使用GitHub上的issue追踪

还有一个scikit-learn的Gitter频道,可能可以找到一些用户和开发人员。

请不要因为寻求帮助,报告错误或与scikit-learn有关的任何其他问题而直接给任意一位作者发送电子邮件。

我应该如何保存、导出或部署估计器(estimators)以进行生产?

请参阅模型持久性

如何创建bunch对象?

请不要创建bunch对象!它们不是scikit-learn API的一部分。bunch对象只是打包一些numpy数组的一种方法。作为scikit-learn的用户,您只需要用numpy数组来为模型提供数据既可。

例如,当训练分类器时,您需要的是输入变量的2D数组X和目标变量的1D数组y。数组X 的列是保存特征值,行是保存样本的数量。该数组y包含整数值,用于存储X中的每个样本的类别。

如何将自己的数据集加载为scikit-learn可用的格式?

通常,scikit-learn可以处理numpy数组或scipy稀疏矩阵存储的任何数值数据。也可以接受其他可转换为数值数组的类型,例如pandas的DataFrame。

有关将数据文件加载为scikit-learn可用数据结构的更多信息,请参考加载外部数据集

新算法的纳入标准是什么?

我们只考虑包括完善的确立已久的算法。按照经验来说,自算法发布以来至少已有3年,被引用200多次以上,并且被广泛使用。我们还考虑将要包括那些提供明显改进和被广泛使用的算法(例如,增强数据结构或更有效的近似技术)。

只有scikit-learn当前API实现那些的算法和技术满足上述标准。他们都被接受了。这些算法都实现了fitpredict/transform接口和通常具有输入/输出的numpy的阵列或稀疏矩阵。

贡献者应通过研究论文和/或其他类似软件包来支持所提出的算法的重要性,并通过常见的用例/应用程序来证明其有用性,通过基准和/或图表来确认性能改进(如果有)。我们期待所提出的算法至少应在某些方面优于scikit-learn中已实现的算法。

在以下情况下,采用新算法加速现有模型更为容易:

  • 它没有引入新的超参数(因为它使库更具前瞻性),
  • 它比较容易清楚地记录何时可以提高速度,什么时候没有提高速度,例如“ when n_features >> n_samples”时,
  • 基准明显显示出速度的加快。

还要注意,您的实现不必为了能与scikit-learn工具一起使用而放在scikit-learn中。您可以通过兼容scikit-learn的方式来实现自己喜欢的算法,然后将其上传到GitHub并通知我们。我们很高兴将其列在相关项目(Related Projects)下。如果您已经在GitHub的scikit-learn API上有发布了一个软件包的话,那么您可能会有兴趣查看scikit-learn-contrib

您为什么会选择scikit-learn中包含的算法?

代码就是维护成本,我们需要在拥有的代码量与团队规模之间进行权衡(由于复杂性规模随功能数量成非线性比例增长的事实)。该软件包依靠核心开发人员利用他们的空闲时间来修复错误,维护代码和检查贡献。添加的任何算法都需要开发人员将来的关注,这时原始作者可能早就失去了兴趣。另请参阅新算法的包含标准是什么?。有关开放源代码软件中长期维护问题的详细信息,请参阅《道路和桥执行摘要(the Executive Summary of Roads and Bridges)》

您为什么从scikit-learn中移除了 HMMs?

请参阅您是否将图模型或序列预测添加到scikit-learn?

您是否会将图模型或序列预测添加到scikit-learn?

在可预见的将来,不会把它们加到scikit-learn中。scikit-learn尝试为机器学习中的基本任务提供统一的API,使用管道和元算法(例如网格搜索)并且将所有内容结合在一起。结构化学习所需的概念,API,算法和专业知识与scikit-learn提供的内容不同。如果我们开始提供任意的结构化学习的包的话,则需要重新设计整个软件包,并且该项目可能会在其自身的重量下崩溃。

这有两个使用类似于scikit-learn的API进行结构化预测的项目:

  • pystruct处理一般的结构化学习(专注于具有近似推理的任意图结构上的SSVM;将样本的概念定义为图结构的实例)
  • seqlearn仅处理序列(专注于精确推理;具有HMM,但主要是出于完整性的考虑;将特征向量视为样本,并对特征向量之间的依赖关系使用偏移编码)

您会添加GPU支持吗?

不,或者至少在不久的将来不会。主要原因是添加GPU支持的话会引入许多软件依赖关系,并会引入特定于平台的问题。scikit-learn旨在易于安装在各种平台上。除神经网络之外,GPU在当今的机器学习中并未发挥重要作用,并且通常可以通过谨慎选择算法来获得更大的速度提升。

您会添加PyPy支持吗?

恐怕您不知道,PyPy是带有内置即时编译器的替代Python的实现。增加了对PyPy3-v5.10 +的实验支持,这需要Numpy 1.14.0+和scipy 1.1.0+。.

我该如何处理字符串数据(或树,图形等)?

scikit-learn估计器(estimators)假定您将为它们提供实值特征向量。这个假设几乎是在所有库中都是硬编码的。但是,您可以通过几种方式将非数字输入提供给估计器(estimators)。

如果您想处理文本文档的话,则可以使用术语频率特征(features);请参阅 内置文本矢量化程序的文本特征提取。有关从任何类型的数据中提取更一般的特征的信息,请参阅 从字典加载特征特征散列

另一个常见的情况是您想处理非数字数据和这些数据上的自定义距离(或相似性)。示例包括具有编辑距离(也称为Levenshtein距离;例如DNA或RNA序列)的字符串。这些可以编码为数字,但是这样做很麻烦且容易出错。可以通过两种方式来处理任意数据上的距离。

首先,许多估计器(estimators)采用预先计算的距离/相似度矩阵,因此,如果数据集不太大的话,则可以计算所有输入对的距离。如果数据集很大,则可以将特征向量与仅一个“特征”一起使用,这是一个独立数据结构的索引,并提供一个自定义度量函数来查找此数据结构中的实际数据。例如,要使用具有Levenshtein距离的DBSCAN:

>>> from leven import levenshtein       
>>> import numpy as np
>>> from sklearn.cluster import dbscan
>>> data = ["ACCTCCTAGAAG", "ACCTACTAGAAGTT", "GAATATTAGGCCGA"]
>>> def lev_metric(x, y):
...     i, j = int(x[0]), int(y[0])     # 抽取索引
...     return levenshtein(data[i], data[j])
...
>>> X = np.arange(len(data)).reshape(-1, 1)
>>> X
array([[0],
       [1],
       [2]])
>>> # 我们需要指定 algoritum='brute' 作为默认的假定(assumes)
>>> # 一个连续的特征空间
>>> dbscan(X, metric=lev_metric, eps=5, min_samples=2, algorithm='brute')
... 
([0, 1], array([ 0,  0, -1]))

(这使用第三方编辑距离包leven。)

对于树内核,图形内核等,可以使用类似的技巧。

为什么有时在OSX或Linux下,n_jobs> 1会导致崩溃/冻结?

一些scikit-learn工具(例如GridSearchCVcross_val_score 内部依赖于Python的multiprocessing模块)通过传递参数n_jobs > 1在Python多个进程上并行执行。

问题在于,由于性能原因,Python的 multiprocessing模块进行fork系统调用的时候不会调用exec接口。许多库(例如,某些版本的Accelerate / vecLib)在OSX,MKL(的某些版本),GCC的OpenMP上运行时,nvidia的Cuda(可能还有许多其他版本)都管理着自己的内部线程池。调用fork时,子进程中的线程池状态被破坏:线程池认为它有很多线程,而只有主线程状态被fork。在这种情况下,可以更改库以使它们检测到何时发生fork就何时重新初始化线程池:我们对OpenBLAS进行了此操作(自0.2.10并入master分支后),并为GCC的OpenMP运行时提供了补丁(尚未审查)。

但真正的原因在于Python 的multiprocessing模块,进行fork系统调用而没有调用exec接口,这会减少启动和使用新的进行并行计算的Python进程的开销。不幸的是,这违反了POSIX标准,因此某些软件编辑器(如Apple)拒绝将Accelerate/vecLib中缺少fork安全性视为bug。

在Python 3.4以上的版本中,现在可以为multiprocessing模块配置使用“forkserver”或“spawn”启动方法(而不是默认的“ fork”)来管理进程池。在使用scikit-learn时要解决此问题的话,可以将JOBLIB_START_METHOD环境变量设置为“forkserver”。但是,用户应注意,使用“forkserver”方法会阻止joblib.Parallel调用在Shell会话中交互定义的函数。

如果您有直接使用multiprocessing而不是使用joblib库的自定义代码,则可为您的程序启用“ forkserver”模式:在主脚本中插入以下代码:

import multiprocessing

# 其他导入语句(import),自定义代码,加载数据,定义模型...

if __name__ == '__main__':
    multiprocessing.set_start_method('forkserver')

    # 调用 scikit-learn工具类,其中,n_jobs>1

您可以在多处理文档中找到有关新启动方法的更多默认设置。

为什么我的作业运行时使用的内核比n_jobs指定的还要多?

这是因为n_jobs仅仅为了joblib能并行化的例程而控制作业(jobs)的数量,而并行代码可以来自其他来源:

  • 某些例程可能与OpenMP并行化(用于用C或Cython编写的代码)。

  • scikit-learn非常依赖numpy,而numpy可能依赖于可以提供并行实现的数值库,例如MKL,OpenBLAS或BLIS。

有关更多详细信息,请参阅我们的Parallelism注释

为什么scikit-learn不支持深度学习或强化学习?/ scikit-learn将会支持深度学习或强化学习吗?

深度学习和强化学习都需要丰富的词汇来定义架构,并且深度学习还需要GPU才能进行有效的计算。但是,这些都不符合scikit-learn的设计约束。所以,深度学习和强化学习目前超出了scikit-learn实现的范围。

您可以在您会添加GPU支持吗?中找到更多有关添加gpu支持的信息。

为什么我的pull请求未能得到关注?

scikit-learn审查过程会花费大量时间,因此贡献者不应该对pull请求还未受到审查而灰心。 我们非常重视第一次就把事情做好,因为维护和后期更改的成本很高。 我们很少发布任何“实验性”代码,因此我们的所有贡献都将立即得到广泛使用,并且最初应具最高质量。

除此之外,scikit-learn的审查能力有限;许多审查人员和核心开发人员都利用自己的时间研究scikit-learn。如果对pull请求的审阅比较慢,很可能是因为审阅者很忙。我们请求您理解,不要仅仅因为这个原因而关闭请求或停止工作。

如何为整个程序设置一个random_states

考虑到测试和可复制性,让单个种子控制整个执行对于具有随机化组件的算法中使用的伪随机数生成器来说通常是很重要的。Scikit learn不使用自己的全局随机状态;当随机状态实例或整数随机种子未作为参数提供时,它依赖于numpy全局随机状态,可以使用 numpy.random.seed设置该状态。例如,要将执行的numpy全局随机状态设置为42,可以在脚本中执行以下操作:

import numpy as np
np.random.seed(42)

但是,全局随机状态在执行期间易于被其他代码修改。 因此,确保可复制性的唯一方法是在各处传递RandomState实例,并确保估计器和交叉验证拆分器均具有其random_state参数集。

比起其他工具,为什么在 scikit-learn 中,多分类变量需要预处理?

大多数scikit-learn假设数据是在单个数字数据类型的NumPy数组或SciPy稀疏矩阵中。目前,这些变量并不明确表示类别变量。因此,与R的data.frames或pandas.DataFrame不同,我们需要将分类特征显式转换为数值,如编码分类特征中所述。 有关使用异构(例如分类和数字)数据的示例,请参见具有混合类型的列转换器

为什么 scikit-learn 不直接跟其它库结合在一起,例如,pandas.DataFrame ?

当前预期的同构NumPy和SciPy数据对象对于大多数操作而言处理效率最高。还需要大量的工作来支持Pandas 的分类类型。因此,将输入限制为相同类型可以降低维护成本,并鼓励使用高效的数据结构。

您是否打算在管道 (pipeline)中实现目标 y 的转换?

当前转换仅适用于管道中的特征X。而关于无法在管道中转换y的问题由来已久。 请查看github问题#4143。 同时查看sklearn.compose.TransformedTargetRegressor。 请注意,scikit-learn解决了y在训练前应用可逆变换,在预测后应用可逆变换的情况。Scikit-learn旨在解决一些用例,其中y应该在训练时而不是在测试时进行转换,以进行重采样和类似用途,例如在不平衡学习中。 一般来说,可以使用自定义元估算器而不是管道来解决这些情况。

(C) 2007 - 2019, scikit-learn 开发人员(BSD许可证)。 Show this page source